package org.ccvi.policy.entity.userinfo;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.ccvi.policy.entity.userinfo.Resource;
import org.ccvi.policy.entity.userinfo.Role;
import org.ccvi.policy.entity.userinfo.Identity;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springside.modules.utils.ReflectionUtils;

@Entity
@Table(name = "pol_user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User extends Identity{

	/**
	 * 
	 */
	private static final long serialVersionUID = -1987197458039325028L;

	private String username;
	private String nameCh;
	private String password;
	private boolean valid;
	private String email;
	private String phone;
	private String address;
	private Date logintime;
	private boolean sex;
	

	private Set<Role> roles = new LinkedHashSet<Role>();

	public User(String username, String nameCh, String password, boolean isValid) {
		super();
		this.username=username;
		this.nameCh = nameCh;
		this.password = password;
		this.valid = isValid;
	}

	public User() {
		super();
	}

	public String getNameCh() {
		return nameCh;
	}

	public void setNameCh(String nameCh) {
		this.nameCh = nameCh;
	}

	@Column(name = "password_", nullable = false, length = 255)
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(name = "is_valid", length = 1)
	public boolean isValid() {
		return valid;
	}

	public void setValid(boolean valid) {
		this.valid = valid;
	}
	
	@Column(name = "username_", length = 20)
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	@Column(name = "email_", length = 20)
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Column(name = "phone_", length = 20)
	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	@Column(name = "address_", length = 100)
	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Column(name = "login_time", length = 20)
	public Date getLogintime() {
		return logintime;
	}

	public void setLogintime(Date logintime) {
		this.logintime = logintime;
	}
	
	@Column(name = "sex_", length = 1)
	public boolean isSex() {
		return sex;
	}

	public void setSex(boolean sex) {
		this.sex = sex;
	}

	@ManyToMany
	@JoinTable(name = "id_user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_id") })
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("id")
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	@Transient
	public Set<Resource> getAllResources() {
		Set<Resource> resources = new LinkedHashSet<Resource>();
		for (Role role : roles) {
			resources.addAll(role.getResources());
		}
		return resources;
	}

	@Transient
	public String getRoleNames() {
		return ReflectionUtils
				.fetchElementPropertyToString(roles, "name", ", ");
	}

	@SuppressWarnings("unchecked")
	@Transient
	public List<Long> getRoleIds() {
		return ReflectionUtils.fetchElementPropertyToList(roles, "id");
	}

	/** 获取用户菜单 */
	@Transient
	public Set<Resource> getAllMenu() {
		return getResourcesByType(Resource.MENU);
	}

	/** 获取用户操作许可 */
	@Transient
	public Set<Resource> getAllOper() {
		return getResourcesByType(Resource.OPER);
	}

	private Set<Resource> getResourcesByType(String type) {
		Set<Resource> resources = new LinkedHashSet<Resource>();
		for (Resource resource : getAllResources()) {
			if (resource.getType().equals(type)) {
				resources.add(resource);
			}
		}
		return resources;
	}
}
